From ff2b49f4fcf2d7198e523fffde0c69e7aec6ec81 Mon Sep 17 00:00:00 2001 From: Debian Multimedia Maintainers Date: Thu, 6 Aug 2026 13:05:03 +0800 Subject: [PATCH] CVE-2026-49346: fix integer overflow in image plane allocation size Origin: upstream, https://github.com/strukturag/libde265/commit/8a1b5cf212f78e1c77cb46eb5d56e492a9336eb8 Bug: https://github.com/strukturag/libde265/security/advisories/GHSA-vv8h-932h-7r86 Bug-Debian: https://bugs.debian.org/1140431 Applied-Upstream: 1.1.0 Large SPS dimensions with 16-bit bit depth overflow the 32-bit allocation size in de265_image_get_buffer(); the wrapped ~1 KB allocation is later written with the full plane size, corrupting the heap. Gbp-Pq: Name CVE-2026-49346.patch --- libde265/image.cc | 50 +++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/libde265/image.cc b/libde265/image.cc index 0ae7751..9ddfed2 100644 --- a/libde265/image.cc +++ b/libde265/image.cc @@ -71,10 +71,11 @@ LIBDE265_API void* de265_alloc_image_plane(struct de265_image* img, int cIdx, void* inputdata, int inputstride, void *userdata) { int alignment = STANDARD_ALIGNMENT; - int stride = (img->get_width(cIdx) + alignment-1) / alignment * alignment; - int height = img->get_height(cIdx); + uint32_t stride = (img->get_width(cIdx) + alignment-1) / alignment * alignment; + uint32_t height = img->get_height(cIdx); - uint8_t* p = (uint8_t *)ALLOC_ALIGNED_16(stride * height + MEMORY_PADDING); + // size computed in size_t: stride*height can exceed UINT32_MAX for large planes + uint8_t* p = static_cast(ALLOC_ALIGNED_16(static_cast(stride) * height + MEMORY_PADDING)); if (p==NULL) { return NULL; } @@ -82,13 +83,15 @@ LIBDE265_API void* de265_alloc_image_plane(struct de265_image* img, int cIdx, // copy input data if provided - if (inputdata != NULL) { - if (inputstride == stride) { - memcpy(p, inputdata, stride*height); + if (inputdata != nullptr) { + if (inputstride == static_cast(stride)) { + memcpy(p, inputdata, static_cast(stride) * height); } else { - for (int y=0;y(y) * stride, + static_cast(inputdata) + static_cast(inputstride) * y, + inputstride); } } } @@ -108,30 +111,35 @@ LIBDE265_API void de265_free_image_plane(struct de265_image* img, int cIdx) static int de265_image_get_buffer(de265_decoder_context* ctx, de265_image_spec* spec, de265_image* img, void* userdata) { - const int rawChromaWidth = spec->width / img->SubWidthC; - const int rawChromaHeight = spec->height / img->SubHeightC; + const uint32_t rawChromaWidth = spec->width / img->SubWidthC; + const uint32_t rawChromaHeight = spec->height / img->SubHeightC; - int luma_stride = (spec->width + spec->alignment-1) / spec->alignment * spec->alignment; - int chroma_stride = (rawChromaWidth + spec->alignment-1) / spec->alignment * spec->alignment; + uint32_t luma_stride = (spec->width + spec->alignment-1) / spec->alignment * spec->alignment; + uint32_t chroma_stride = (rawChromaWidth + spec->alignment-1) / spec->alignment * spec->alignment; assert(img->BitDepth_Y >= 8 && img->BitDepth_Y <= 16); assert(img->BitDepth_C >= 8 && img->BitDepth_C <= 16); - int luma_bpl = luma_stride * ((img->BitDepth_Y+7)/8); - int chroma_bpl = chroma_stride * ((img->BitDepth_C+7)/8); + uint32_t luma_bpl = luma_stride * ((img->BitDepth_Y+7)/8); + uint32_t chroma_bpl = chroma_stride * ((img->BitDepth_C+7)/8); - int luma_height = spec->height; - int chroma_height = rawChromaHeight; + uint32_t luma_height = spec->height; + uint32_t chroma_height = rawChromaHeight; bool alloc_failed = false; - uint8_t* p[3] = { 0,0,0 }; - p[0] = (uint8_t *)ALLOC_ALIGNED_16(luma_height * luma_bpl + MEMORY_PADDING); - if (p[0]==NULL) { alloc_failed=true; } + // Compute the plane sizes in size_t. Each operand fits in uint32_t, but the + // height * bytes-per-line product can exceed UINT32_MAX for large frames, so + // the multiplication must be done in 64 bits. Computing it in 32 bits wraps + // the allocation size to a small value while fill_image() later writes the + // real (size_t) size -> heap buffer overflow (GHSA-vv8h-932h-7r86). + uint8_t* p[3] = { nullptr,nullptr,nullptr }; + p[0] = static_cast(ALLOC_ALIGNED_16(static_cast(luma_height) * luma_bpl + MEMORY_PADDING)); + if (p[0]==nullptr) { alloc_failed=true; } if (img->get_chroma_format() != de265_chroma_mono) { - p[1] = (uint8_t *)ALLOC_ALIGNED_16(chroma_height * chroma_bpl + MEMORY_PADDING); - p[2] = (uint8_t *)ALLOC_ALIGNED_16(chroma_height * chroma_bpl + MEMORY_PADDING); + p[1] = static_cast(ALLOC_ALIGNED_16(static_cast(chroma_height) * chroma_bpl + MEMORY_PADDING)); + p[2] = static_cast(ALLOC_ALIGNED_16(static_cast(chroma_height) * chroma_bpl + MEMORY_PADDING)); if (p[1]==NULL || p[2]==NULL) { alloc_failed=true; } } -- 2.30.2